// 顶部：仅类型导入 + 拆分 logger 的值/类型导入
import Logger from "../../logger";
import type { ILogger } from "../../logger";
import { LoggerLevel } from "../../logger";
import type { IContrastArrayParams, IContrastArrayResult, IContrastVersionParams, IUtilsContrast } from "./contrast";
import utilsIs from "../is";
import bignumber from "../../bignumber";

export type {
    IUtilsContrast,
    IContrastArrayParams, IContrastArrayResult, IContrastVersionParams,
}

class UtilsContrast implements IUtilsContrast {
    private logger: ILogger;

    constructor(loggerLevel?: LoggerLevel) {
        this.logger = new Logger("utils_contrast", loggerLevel);
    }

    version(serverVersion: string, localVersion: string, params?: IContrastVersionParams): boolean {
        params = params || {};
        const serverBuild = params.serverBuild ?? 0;
        const localBuild = params.localBuild ?? 0;
        const serverSplit = serverVersion.split('.');
        const localSplit = localVersion.split('.');
        let sNum = 0, lNum = 0;
        for (let i = 0, len = serverSplit.length; i < len; i++) {
            sNum = bignumber.add(sNum, serverSplit[i]);
            lNum = bignumber.add(lNum, localSplit[i]);
            if (sNum > lNum) return true;
            else if (sNum < lNum) return false;
        }
        return Number(serverBuild) > Number(localBuild);
    }

    json<T>(jsonOne: T, jsonTwo: T): boolean {
        const isJsonOne = utilsIs.json(jsonOne);
        const isJsonTwo = utilsIs.json(jsonTwo);
        if (!isJsonOne) {
            this.logger.warn('contrastJson()', 'jsonOne 不是有效的 JSON 对象');
            return false;
        }
        if (!isJsonTwo) {
            this.logger.warn('contrastJson()', 'jsonTwo 不是有效的 JSON 对象');
            return false;
        }
        return JSON.stringify(jsonOne) === JSON.stringify(jsonTwo);
    }

    jsonToDiff<T>(oldJson: object, newJson: object): T {
        const isJsonOld = utilsIs.json(oldJson);
        const isJsonNew = utilsIs.json(newJson);
        if (!isJsonOld) {
            this.logger.warn('contrastJsonToDiff()', 'oldJson 不是有效的 JSON 对象');
            return {} as T;
        }
        if (!isJsonNew) {
            this.logger.warn('contrastJsonToDiff()', 'newJson 不是有效的 JSON 对象');
            return {} as T;
        }
        if (this.json(oldJson, newJson)) return {} as T;

        const result: Record<string, any> = {};  // 使用Record类型定义索引签名
        for (let item in newJson) {
            if ((newJson as Record<string, any>)[item] !== (oldJson as Record<string, any>)[item]) {
                result[item] = (newJson as Record<string, any>)[item];
            }
        }
        return result as T;
    }

    private findDiffItem<T>(oldArr: T[], newArr: T[], fields?: string[]): T[] {
        const diffList: T[] = [];
        oldArr.forEach((item: any) => {
            const hasExist = newArr.some((m: any) => {
                if (fields && fields.length > 0) {
                    return fields.every((name: string) => m[name] === item[name]);
                }
                const isJson = utilsIs.json(item);
                if (isJson) return this.json(m, item);
                return m === item;
            });
            if (!hasExist) diffList.push(item);
        });
        return diffList;
    }

    arrayToDiff<T>(oldArr: T[], newArr: T[], params?: IContrastArrayParams): IContrastArrayResult<T> {
        params = params || {};
        const fields = params.fields ?? [];
        const isArrayOld = utilsIs.array(oldArr);
        const isArrayNew = utilsIs.array(newArr);
        const result: IContrastArrayResult<T> = {newDiff: [], oldDiff: []};

        if (!isArrayOld) {
            this.logger.warn('contrastArrayToDiff()', 'oldArr 不是有效的数组');
            return result;
        }
        if (!isArrayNew) {
            this.logger.warn('contrastArrayToDiff()', 'newArr 不是有效的数组');
            return result;
        }

        result.oldDiff = this.findDiffItem(oldArr, newArr, fields);
        result.newDiff = this.findDiffItem(newArr, oldArr, fields);
        return result;
    }
}

export default new UtilsContrast() as IUtilsContrast;
